package lime2;

//: containers/ListPerformance.java
// Demonstrates performance differences in Lists.
// {Args: 100 500} Small to keep build testing short
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import lights.adapters.TupleSpaceFactory;
import lights.interfaces.ITuple;
import sagroup.util.Limes;
import sagroup.util.Test;
import sagroup.util.TestParam;
import sagroup.util.Tester;

public class LTSMPerformance {
	static List<Test<LimeTSMgr>> ltsmTestsWithReaction = new ArrayList<Test<LimeTSMgr>>();;
	static List<Test<LimeTSMgr>> ltsmTestsWithoutReaction = new ArrayList<Test<LimeTSMgr>>();;
	static {
		Test<LimeTSMgr> ltsmt = (new Test<LimeTSMgr>("out") {
			public int test(LimeTSMgr list, TestParam tp) {
				int loops = tp.loops;
				int listSize = tp.size;
				int total = 0;
				for (int i = 0; i < loops; i++) {
					for (int j = 0; j < listSize; j++) {
						list
								.doWrite(new ITuple[] { TestData.allTuples[total++] });
					}
				}
				return loops * listSize;
			}
		});
		ltsmTestsWithReaction.add(ltsmt);
		ltsmTestsWithoutReaction.add(ltsmt);
	}

	static class LTSMTester extends Tester<LimeTSMgr> {
		public LTSMTester(LimeTSMgr container, List<Test<LimeTSMgr>> tests) {
			super(container, tests);
		}
	}

	static class HasReactionLTSMTester extends LTSMTester {
		int reactionsLen;

		public HasReactionLTSMTester(LimeTSMgr container,
				List<Test<LimeTSMgr>> tests, int reactionsLen) {
			super(container, tests);
			this.reactionsLen = reactionsLen;
		}

		@Override
		// Fill reactions to the appropriate size before each test:
		protected LimeTSMgr initialize(int size) {
			for (int i = 0; i < reactionsLen; i++) {
				container.registerStrong(
						new Reaction[] { TestData.allReactions[i] }, container
								.nextPureStrongRID(1));
			}
			return container;
		}
	}

	private static int tsCounter = 0;

	public static void main(String[] args) throws Exception {
		// , 100, 5000);
		// , 1000, 1000,
		// 10000, 200);
		if (args.length > 0)
			Tester.defaultParams = TestParam.array(args);
		Location.initHere((new LimeServerID(InetAddress.getLocalHost(), 8080)));
		TupleSpaceFactory
				.setFactory("lights.adapters.builtin.TupleSpaceFactory");
		// Limes.startServer();
		Logger logger = Logger.getLogger("");
		logger.setLevel(Level.OFF);
		int tuplesize = 100;
		int reactionsize = 10000;
		Tester.defaultParams = TestParam.array(tuplesize, 1);
		// load TestData class.
		TestData.generate(tuplesize, reactionsize);
		Reaction reaction = TestData.allReactions[0];
		logger.info(reaction.toString());
		ITuple t = TestData.allTuples[0];
		ITuple p = TestData.allTemplates[0];
		logger.info(t.toString());
		logger.info(p.toString());
		// run(true, false, 0, 10);
		// run(false, false, 0, 10);
		int[] rss = new int[] { 5000, 1000, 500, 100 };
		for (int i = 0; i < rss.length; i++) {
			run(true, false, rss[i], 5);
			run(false, false, rss[i], 5);
		}
	}

	private static void run(int hasReactions) {
		String s1 = (LimeTSMgr.useReactionTree ? "optimized" : "original");
		String s2 = (LimeTSMgr.useSingleThread ? "single thread" : "concurrent");
		String s3 = hasReactions > 0 ? "with reactions" : "without reactions";
		String title = "LTSM test " + s1 + " " + s2 + " " + s3;
		Tester t;
		if (hasReactions > 0) {
			t = new HasReactionLTSMTester(LimeTSMgr.creatLTSM("ts"
					+ tsCounter++, (byte) 0), ltsmTestsWithReaction,
					hasReactions);
		} else {
			t = new LTSMTester(LimeTSMgr
					.creatLTSM("ts" + tsCounter++, (byte) 0),
					ltsmTestsWithoutReaction);

		}
		Tester.run(t, title);
	}

	private static void run(boolean useReactionTree, boolean useSingleThread,
			int reactionsLen, int loops) {
		LimeTSMgr.useReactionTree = useReactionTree;
		LimeTSMgr.useSingleThread = useSingleThread;
		for (int i = 0; i < loops; i++) {
			run(reactionsLen);
		}
	}
}
